﻿using AutoMapper;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using WMS.FC.Application.System.Interface;
using WMS.FC.Domain.DataTransferObject.System;
using WMS.FC.Domain.DomainObject.System;
using WMS.FC.Domain.Repository;
using WMS.FC.Domain.Service.System.Interface;
using WMS.FC.Domain.ValueObject.System;

namespace WMS.FC.Application.System
{
    public class SystemService : ServiceBase, ISystemService
    {
        protected readonly IAddDataService addDataService;
        protected readonly IBatchEditDataService batchEditDataService;
        protected readonly IEditDataService editDataService;
        protected readonly IExportDataService exportDataService;
        protected readonly IGetDictionaryService getDictionaryService;
        protected readonly IGetPageConfigService getPageConfigService;
        protected readonly IGetPageDataService getPageDataService;
        protected readonly IOperateDataService operateDataService;
        protected readonly IViewDataService viewDataService;

        public SystemService(
            ILogger<ServiceBase> logger,
            IOptions<WmsSettings> options,
            IMapper mapper,
            IUnitOfWork unitOfWork,
            IAddDataService addDataService,
            IBatchEditDataService batchEditDataService,
            IEditDataService editDataService,
            IExportDataService exportDataService,
            IGetDictionaryService getDictionaryService,
            IGetPageConfigService getPageConfigService,
            IGetPageDataService getPageDataService,
            IOperateDataService operateDataService,
            IViewDataService viewDataService)
            : base(logger, options, mapper, unitOfWork)
        {
            this.addDataService = addDataService;
            this.batchEditDataService = batchEditDataService;
            this.editDataService = editDataService;
            this.exportDataService = exportDataService;
            this.getDictionaryService = getDictionaryService;
            this.getPageConfigService = getPageConfigService;
            this.getPageDataService = getPageDataService;
            this.operateDataService = operateDataService;
            this.viewDataService = viewDataService;
        }

        public async Task<ResponseBase> GetPageConfig(GetPageConfigDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(async () =>
                {
                    var getPageConfigResult = await getPageConfigService.GetPageConfig(dTO.MenuId, dTO.UserInfo);
                    if (getPageConfigResult.IsSuccess)
                    {
                        var getDictionaryResult = await getDictionaryService.GetDictionary(dTO.MenuId, dTO.UserInfo);
                        if (getDictionaryResult.IsSuccess)
                        {
                            getPageConfigResult.Data!.Dictionary = getDictionaryResult.Data!.Dictionary;
                        }
                    }

                    return getPageConfigResult;
                });

                response = response.TransferResult(result, mapper.Map<PageConfigVO>);
            }
            catch (Exception ex)
            {
                return response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> GetPageData(GetPageDataDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(() =>
                {
                    return getPageDataService.GetPageData(dTO.MenuId, dTO.Query, dTO.Pagination, dTO.Sorter, dTO.UserInfo);
                });

                response = response.TransferResult(result, mapper.Map<PageDataVO>);
            }
            catch (Exception ex)
            {
                return response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> GetDictionary(GetDictionaryDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(async () =>
                {
                    return await getDictionaryService.GetDictionary(dTO.MenuId, dTO.UserInfo);
                });

                response = response.TransferResult(result, mapper.Map<DictionaryVO>);
            }
            catch (Exception ex)
            {
                return response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> GetDictionaryType(RequestBase dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(async () =>
                {
                    return await getDictionaryService.GetDictionaryType(dTO.UserInfo);
                });

                response = response.TransferResult(result, mapper.Map<DictionaryVO>);
            }
            catch (Exception ex)
            {
                return response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> AddData(HandleButtonDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(() =>
                {
                    return addDataService.AddData(dTO.MenuId, dTO.Value, dTO.UserInfo);
                });

                response = response.TransferResult(result);
            }
            catch (Exception ex)
            {
                return response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> EditData(HandleButtonDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(() =>
                {
                    return editDataService.EditData(dTO.MenuId, dTO.Value, dTO.SelectedIds, dTO.UserInfo);
                });

                response = response.TransferResult(result);
            }
            catch (Exception ex)
            {
                return response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> BatchEditData(HandleButtonDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(() =>
                {
                    return batchEditDataService.BatchEditData();
                });

                response = response.TransferResult(result);
            }
            catch (Exception ex)
            {
                return response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> ViewData(HandleButtonDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(() =>
                {
                    return viewDataService.ViewData();
                });

                response = response.TransferResult(result);
            }
            catch (Exception ex)
            {
                return response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> ExportData(HandleButtonDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(() =>
                {
                    return exportDataService.ExportData();
                });

                response = response.TransferResult(result);
            }
            catch (Exception ex)
            {
                return response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> OperateData(HandleButtonDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(() =>
                {
                    return operateDataService.OperateData(dTO.MenuId, dTO.SelectedIds, dTO.UserInfo);
                });

                response = response.TransferResult(result);
            }
            catch (Exception ex)
            {
                return response.Exception(ex);
            }

            return response;
        }
    }
}